"""
When Python sees a statement like for x in foo, it actually calls iter(foo). The iter built-in
function calls the foo.__iter__ special method in turn. The __iter__
method must return an iterator object (which itself implements the
__next__ special method). Then, the for loop repeatedly calls the
next built-in function on the iterator object until it’s exhausted (indicated by raising a StopIteration exception)
"""
import collections


class ReadFile:

    def __init__(self, path, enc='utf8'):
        self.path = path
        self.enc = enc

    def __iter__(self):
        with open(self.path, 'r', encoding=self.enc) as f:
            for line in f:
                yield line


def is_iter(obj):
    return iter(obj) is obj


def is_iter_via_abc(obj):
    return isinstance(obj, collections.abc.Iterator)


if '__main__' == __name__:
    from PyCmpltrtok.common import sep

    N = 5

    path = r'D:\_dell7590_root\local\LNP_datasets\med\med_dialog\MedDialog_processed\MedDialog_processed\train_data.json'
    obj = ReadFile(path)
    xiter = iter(obj)
    print('obj:', 'is iter?', is_iter(obj), is_iter_via_abc(obj))
    print('xiter:', 'is iter?', is_iter(xiter), is_iter_via_abc(xiter))

    sep('next(xiter)')
    for i in range(N):
        n = i + 1
        line = next(xiter)
        print(n, f'|{line}|')

    sep('next(xiter) AGAIN')  # further lines
    for i in range(N):
        n = i + 1
        line = next(xiter)
        print(n, f'|{line}|')

    sep('for(obj) 1st')
    for i, line in enumerate(obj):
        if i >= N:
            break
        n = i + 1
        print(n, f'|{line}|')

    sep('for(obj) 2nd')
    for i, line in enumerate(obj):
        if i >= N:
            break
        n = i + 1
        print(n, f'|{line}|')

    sep('for(iter)')
    xiter = iter(obj)
    print('xiter:', 'is iter?', is_iter(xiter), is_iter_via_abc(xiter))
    for i, line in enumerate(xiter):
        if i >= N:
            break
        n = i + 1
        print(n, f'|{line}|')

    print('All over')
